home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 4 / MacMania 4.toast / / Demo's / Igor Demo Pro / 1 PutContentsIn Igor Pro Folder / WaveMetrics Procedures / Data Manipulation / Drag Spline < prev    next >
Text File  |  1996-01-29  |  13KB  |  421 lines

  1. | Version 1.01, 5/17/94
  2. |    Used Wave/D instead of Wave in several places.
  3. | Version 1.02, 7/7/94
  4. |    Changed DisEstablishSplineDependency so that it correctly breaks the dependency.
  5. | Version 1.10, 12/31/95
  6. |    Updated for Igor Pro 3.0.
  7. |    However, these procedures will work only if the source waves are in the current data folder.
  8.  
  9. | Drag Spline
  10. |    These procedures are designed to help you put a smooth curve through
  11. |    a noisy data set with a large number of points.
  12. |    To use them:
  13. |        Choose Add Spline Controls’ from the Macros menu. This will add some controls to the top graph.
  14. |        Choose a data set from the Input Data popup menu.
  15. |        Click the Start Spline Drag button.
  16. |        Drag the spline nodes (black dots) around.
  17. |        Click Stop Spline Drag when you are done.
  18. |     See the example experiment "Drag Spline Demo" in the "Examples" folder for further details.
  19.  
  20. #pragma rtGlobals = 1
  21.  
  22. #include <Wave Lists>, menus=0
  23. #include <Decimation>, menus=0
  24.  
  25. Menu "Macros"
  26.     "Add Spline Controls"
  27.     help = {"Adds some controls to the active graph. The controls make it easy to interactively put a smooth spline through a fairly large set of noisy data."}
  28. End
  29.  
  30. | CheckDragSplineGlobals()
  31. |    Creates global settings used by other routines if they do not already exist.
  32. |    In most cases you will not need to tweak these globals.
  33. Function CheckDragSplineGlobals()
  34.     NewDataFolder/O root:Packages
  35.     NewDataFolder/O root:Packages:'Drag Spline'
  36.     if (exists("root:Packages:'Drag Spline':gNumNodes") == 0)
  37.         Variable/G root:Packages:'Drag Spline':gNumNodes=20                    | number of nodes through which spline is to be drawn
  38.         Variable/G root:Packages:'Drag Spline':gNumOutputPoints=200        | length of spline waves
  39.     endif
  40. End
  41.  
  42. | SetSplineDragWaves(xDataWave, yDataWave)
  43. |    Sets the "Input Data" popup menu.
  44. |    The menu may contain one or two items.
  45. |    The first item is always "Choose Input Data".
  46. |    If the user has never chosen input data then there will be no second item.
  47. |    Otherwise, the second item will be something like:
  48. |        "data"                    if the input data is waveform data
  49. |    or
  50. |        "yData vs xData"        if the input data is XY data
  51. |    All other routines determine the input data by interrogating this popup menu
  52. |    which acts as graph-local storage for the drag spline routines.
  53. Function SetSplineDragWaves(xDataWave, yDataWave)
  54.     String xDataWave
  55.     String yDataWave
  56.     
  57.     String s
  58.     Variable selectedItem
  59.     
  60.     | Make sure that the names of the node and spline waves won't be too long
  61.     if ((strlen(xDataWave) > 27) %| (strlen(yDataWave) > 27))
  62.         Abort "Sorry, the input data wave names must not exceed 27 characters in length"
  63.     endif
  64.     
  65.     s = "Choose Input Data...;"
  66.     if (strlen(yDataWave) == 0)                    | if yDataWave == "" then we are clearing data waves
  67.         selectedItem = 1
  68.     else
  69.         selectedItem = 2
  70.         if (strlen(xDataWave) > 0)                    | XY data ?
  71.             s += yDataWave + " vs " + xDataWave
  72.         else                                            | waveform data
  73.             s += yDataWave
  74.         endif
  75.     endif
  76.     String cmd
  77.     sprintf cmd, "PopupMenu DragSpline_DataWaves, mode=%d, value=%s", selectedItem, "\"" + s + "\""
  78.     Execute cmd
  79. End
  80.  
  81. | SplineDragIsXYData()
  82. |    Returns true if the chosen input data is XY data, false if it is waveform data.
  83. Function SplineDragIsXYData()
  84.     String popupText
  85.     
  86.     ControlInfo DragSpline_DataWaves        | Sets S_value string
  87.     popupText = S_value                        | e.g. "yWave vs xWave"
  88.     return strsearch(popupText, " vs ", 0) > 0
  89. End
  90.  
  91. | SplineDragDataWave(xy)
  92. |    Returns the name of the x or y input data wave.
  93. |    If the input data is waveform rather than XY data, it returns "" for x wave name.
  94. |    This works by interrogating the input data popup menu.
  95. Function/S SplineDragDataWave(xy)
  96.     Variable xy                                | 1 for x, 2 for y
  97.     
  98.     String popupText
  99.     String xw, yw
  100.     
  101.     ControlInfo DragSpline_DataWaves        | Sets S_value string
  102.     popupText = S_value                        | e.g. "yWave vs xWave"
  103.     
  104.     if (SplineDragIsXYData())                | for XY data popup contains "yData vs xData"
  105.         if (xy == 1)
  106.             return popupText[strsearch(popupText," vs",0)+4, strlen(popupText)]
  107.         else
  108.             return popupText[0, strsearch(popupText," vs",0)-1]
  109.         endif
  110.     else                                        | for waveform data popup contains "data"
  111.         if (xy == 1)
  112.             return ""                            | signifies no x wave
  113.         else
  114.             return popupText
  115.         endif
  116.     endif
  117. End
  118.  
  119. Function/S SplineDragXDataWave()            | returns x data wave name or "" for waveform data
  120.     return SplineDragDataWave(1)
  121. End
  122.  
  123. Function/S SplineDragYDataWave()            | returns y data wave
  124.     return SplineDragDataWave(2)
  125. End
  126.  
  127. Function/S NodeWaveSuffix()
  128.     return "_N"
  129. End
  130.  
  131. Function/S SplineWaveSuffix()
  132.     return "_CS"
  133. End
  134.  
  135. |  SplineDragPrefix(xy)
  136. |    Prefixes are used for waveform data only.
  137. |    If the input data wave name is "data" then the node and spline wave names will be:
  138. |        xdata_N, ydata_N, xdata_CS and ydata_CS
  139. Function/S SplineDragPrefix(xy)
  140.     Variable xy                                | 1 for x, 2 for y
  141.  
  142.     if (xy == 1)
  143.         return "x"
  144.     else
  145.         return "y"
  146.     endif
  147. End    
  148.  
  149. | SplineDragNodeWave(xy)
  150. |    If the input data is "yData vs xData" (XY data) then the node names will be:
  151. |        xData_N, yData_N
  152. |    If the input data is "data" (waveform data) then the node names will be:
  153. |        xdata_N, ydata_N
  154. Function/S SplineDragNodeWave(xy)    
  155.     Variable xy                                | 1 for x, 2 for y
  156.     
  157.     String s
  158.     
  159.     if (SplineDragIsXYData())
  160.         s = SplineDragDataWave(xy)
  161.     else
  162.         s = SplineDragPrefix(xy) + SplineDragYDataWave()
  163.     endif
  164.     
  165.     return s + NodeWaveSuffix()
  166. End
  167.  
  168. | SplineDragSplineWave(xy)
  169. |    If the input data is "yData vs xData" (XY data) then the spline names will be:
  170. |        xData_CS, yData_CS
  171. |    If the input data is "data" (waveform data) then the spline names will be:
  172. |        xdata_CS, ydata_CS
  173. Function/S SplineDragSplineWave(xy)
  174.     Variable xy                                | 1 for x, 2 for y
  175.     
  176.     String s
  177.     
  178.     if (SplineDragIsXYData())
  179.         s = SplineDragDataWave(xy)
  180.     else
  181.         s = SplineDragPrefix(xy) + SplineDragYDataWave()
  182.     endif
  183.     
  184.     return s + SplineWaveSuffix()
  185. End
  186.  
  187. Function RecalcSpline(p, xNodeWave, yNodeWave, xSplineWave, ySplineWave, preaverageNodes)
  188.     Variable p                        | point number
  189.     Wave xNodeWave                | x wave through which spline is to be drawn
  190.     Wave yNodeWave                | y wave through which spline is to be drawn
  191.     Wave xSplineWave            | x output wave
  192.     Wave ySplineWave            | y output wave
  193.     Variable preaverageNodes        | preaveraging -- normally zero for no preaveraging
  194.     
  195.     String cmd
  196.     Variable numOutPoints
  197.     
  198.     if (p == 0)
  199.         String xSW = PossiblyQuoteName(NameOfWave(xSplineWave))
  200.         String ySW = PossiblyQuoteName(NameOfWave(ySplineWave))
  201.         String xNW = PossiblyQuoteName(NameOfWave(xNodeWave))
  202.         String yNW = PossiblyQuoteName(NameOfWave(yNodeWave))
  203.         numOutPoints = numpnts(ySplineWave)
  204.         sprintf cmd, "Interpolate/N=(%d)/A=(%d)/Y=%s/X=%s %s /X=%s", numOutPoints, preaverageNodes, ySW, xSW, yNW, xNW
  205.         Execute cmd
  206.     endif
  207.     
  208.     return ySplineWave[p]
  209. End
  210.  
  211. Function EstablishSplineDependency(xNodeWave, yNodeWave, xSplineWave, ySplineWave)
  212.     String xNodeWave, yNodeWave, xSplineWave, ySplineWave
  213.  
  214.     String formula
  215.     
  216.     | This establishes the dependency that causes the spline wave to be updated
  217.     | when you drag the node wave
  218.     String xSW = PossiblyQuoteName(xSplineWave)
  219.     String ySW = PossiblyQuoteName(ySplineWave)
  220.     String xNW = PossiblyQuoteName(xNodeWave)
  221.     String yNW = PossiblyQuoteName(yNodeWave)
  222.     sprintf formula, "RecalcSpline(p, %s, %s, %s, %s, 0)", xNW, yNW, xSW, ySW
  223.     SetFormula $ySplineWave, formula
  224. End
  225.  
  226. Function DisEstablishSplineDependency(ySplineWave)
  227.     String ySplineWave
  228.  
  229.     SetFormula $ySplineWave, ""
  230. End
  231.  
  232. Function MakeNodeAndSplineWaves()
  233.     CheckDragSplineGlobals()
  234.  
  235.     String xDataWave, yDataWave
  236.     
  237.     xDataWave = SplineDragXDataWave()            | x data wave name or "" for waveform data()
  238.     yDataWave = SplineDragYDataWave()
  239.     
  240.     NVAR numOutputPoints = root:Packages:'Drag Spline':gNumOutputPoints        | typically 200
  241.     NVAR numNodes=root:Packages:'Drag Spline':gNumNodes                        | typically 20
  242.     Variable decimationFactor = numpnts($yDataWave)/numNodes
  243.     
  244.     String xNodeWave                    | x wave through which spline is to be drawn
  245.     String yNodeWave                    | y wave through which spline is to be drawn
  246.     String xSplineWave                | x output wave
  247.     String ySplineWave                | y output wave
  248.  
  249.     | Create x node wave by decimating input data
  250.     xNodeWave = SplineDragNodeWave(1)
  251.     if (strlen(xDataWave) > 0)        | XY data ?
  252.         FDecimate($xDataWave, xNodeWave, decimationFactor)
  253.     else
  254.         Duplicate/O $yDataWave, tempXDataWave9999 
  255.         tempXDataWave9999 = x
  256.         FDecimate(tempXDataWave9999, xNodeWave, decimationFactor)
  257.         KillWaves/Z tempXDataWave9999
  258.     endif
  259.  
  260.     | Create y node wave by decimating input data
  261.     yNodeWave = SplineDragNodeWave(2)
  262.     FDecimate($yDataWave, yNodeWave, decimationFactor)
  263.  
  264.     | Create output spline waves
  265.     xSplineWave = SplineDragSplineWave(1)
  266.     ySplineWave = SplineDragSplineWave(2)
  267.     Make/O/N=(numOutputPoints) $xSplineWave, $ySplineWave
  268.     Wave xW = $xSplineWave
  269.     xW = NaN
  270.     Wave yW = $ySplineWave
  271.     yW = NaN
  272.     RecalcSpline(0, $xNodeWave, $yNodeWave, $xSplineWave, $ySplineWave, 0)
  273. End
  274.  
  275. Function AppendNodeAndSplineWaves()
  276.     String xNodeWave, yNodeWave
  277.     String xSplineWave, ySplineWave
  278.     
  279.     xNodeWave = SplineDragNodeWave(1)
  280.     yNodeWave = SplineDragNodeWave(2)
  281.     CheckDisplayed $yNodeWave
  282.     if (V_flag == 0)
  283.         AppendToGraph $yNodeWave vs $xNodeWave
  284.         ModifyGraph rgb($yNodeWave)=(0, 0, 0), mode($yNodeWave)=3, marker($yNodeWave)=19, msize($yNodeWave)=3
  285.     endif
  286.     
  287.     xSplineWave = SplineDragSplineWave(1)
  288.     ySplineWave = SplineDragSplineWave(2)
  289.     CheckDisplayed $ySplineWave
  290.     if (V_flag == 0)
  291.         AppendToGraph $ySplineWave vs $xSplineWave
  292.         ModifyGraph rgb($ySplineWave)=(0, 0, 65535), lsize($ySplineWave)=2
  293.     endif
  294. End
  295.  
  296. Function RemoveAndKillNodeSplineWaves()
  297.     String xNodeWave                | x wave through which spline is to be drawn
  298.     String yNodeWave                | y wave through which spline is to be drawn
  299.  
  300.     xNodeWave = SplineDragNodeWave(1)
  301.     yNodeWave = SplineDragNodeWave(2)
  302.     CheckDisplayed $yNodeWave
  303.     if (V_flag != 0)
  304.         RemoveFromGraph $yNodeWave
  305.     endif
  306.     KillWaves/Z $xNodeWave, $yNodeWave
  307. End
  308.  
  309. Proc ChooseSplineWavesDialog(yDataWave)
  310.     String yDataWave = SplineDragYDataWave()
  311.     Prompt yDataWave, "Y Data Wave", popup GraphWaveList("", "*", 0, 1, ";")
  312.     
  313.     String xDataWave
  314.     xDataWave = XWaveName("", yDataWave)        | will be wave name for XY data or "" for waveform data
  315.     SetSplineDragWaves(xDataWave, yDataWave)
  316. End
  317.  
  318. Function ChooseSplineWaves(ctrlName,popNum,popStr) : PopupMenuControl
  319.     String ctrlName
  320.     Variable popNum
  321.     String popStr
  322.     
  323.     if (popNum == 1)                                    | The popup has two items. The first is Choose...
  324.         Execute("ChooseSplineWavesDialog()")        | and the second identifies the actual waves chosen
  325.         MakeNodeAndSplineWaves()
  326.         AppendNodeAndSplineWaves()
  327.     endif
  328. End
  329.  
  330. Function AddSplineControls()
  331.     CheckDragSplineGlobals()
  332.     
  333.     if (Wintype("") != 1)
  334.         Abort "Activate a graph before showing the spline controls"
  335.     endif
  336.     
  337.     ControlInfo DragSpline_DataWaves        | don't add the controls twice
  338.     if (V_value == 3)                            | this should be a popup menu
  339.         Abort "The controls are already in the active graph"
  340.     endif
  341.     
  342.     ShowTools
  343.     ControlBar 60
  344.     Button StartStopSplineDrag,pos={27,30},size={140,20},proc=StartSplineDrag,title="Start Spline Drag"
  345.     PopupMenu DragSpline_DataWaves,pos={24,5},size={211,19},proc=ChooseSplineWaves,title="Input Data:"
  346.     PopupMenu DragSpline_DataWaves,mode=1,value= #"\"Choose Input Data...\""
  347.     Button RemoveSplineControls,pos={249,30},size={65,20},proc=RemoveSplineControls,title="All Done"
  348. End
  349.  
  350. Function RemoveSplineControls(ctrlName) : ButtonControl
  351.     String ctrlName
  352.  
  353.     ControlInfo PauseResumeSplineDrag        | button will exist if dragging was started
  354.     if (V_flag != 0)
  355.         StopSplineDrag(ctrlName)
  356.     endif
  357.     
  358.     // Node waves will be in graph if the user chose the input data but never started the spline drag.
  359.     RemoveAndKillNodeSplineWaves()
  360.     
  361.     KillControl RemoveSplineControls
  362.     KillControl StartStopSplineDrag
  363.     KillControl DragSpline_DataWaves
  364.     ControlBar 0
  365.     HideTools
  366. End
  367.  
  368. Function PauseSplineDrag(ctrlName) : ButtonControl
  369.     String ctrlName
  370.  
  371.     GraphNormal
  372.     Button PauseResumeSplineDrag, title="Resume", proc=ResumeSplineDrag
  373. End
  374.  
  375. Function ResumeSplineDrag(ctrlName) : ButtonControl
  376.     String ctrlName
  377.     
  378.     String yNodeWave = SplineDragNodeWave(2)
  379.  
  380.     Button PauseResumeSplineDrag, title="Pause", proc=PauseSplineDrag
  381.     GraphWaveEdit $yNodeWave
  382. End
  383.  
  384. Function StartSplineDrag(ctrlName) : ButtonControl
  385.     String ctrlName
  386.     
  387.     String xNodeWave, yNodeWave, xSplineWave, ySplineWave
  388.     Variable yNodeWaveMissing, ySplineWaveMissing
  389.  
  390.     xNodeWave = SplineDragNodeWave(1)
  391.     yNodeWave = SplineDragNodeWave(2)
  392.     xSplineWave = SplineDragSplineWave(1)
  393.     ySplineWave = SplineDragSplineWave(2)
  394.     
  395.     if (exists(ySplineWave) != 1)
  396.         Abort "You need to choose input data. Use the Input Data popup menu."
  397.     endif
  398.     
  399.     CheckDisplayed $yNodeWave; yNodeWaveMissing = V_flag==0
  400.     CheckDisplayed $ySplineWave; ySplineWaveMissing = V_flag==0
  401.     if (yNodeWaveMissing %| ySplineWaveMissing)
  402.         MakeNodeAndSplineWaves()
  403.         AppendNodeAndSplineWaves()
  404.     endif
  405.     
  406.     EstablishSplineDependency(xNodeWave, yNodeWave, xSplineWave, ySplineWave)
  407.     Button startStopSplineDrag, title="Stop Spline Drag", proc=StopSplineDrag
  408.     Button PauseResumeSplineDrag,pos={175,30},size={65,20},proc=PauseSplineDrag,title="Pause"
  409.     GraphWaveEdit $yNodeWave
  410. End
  411.  
  412. Function StopSplineDrag(ctrlName) : ButtonControl
  413.     String ctrlName
  414.     
  415.     DisEstablishSplineDependency(SplineDragSplineWave(2))
  416.     Button startStopSplineDrag, title="Start Spline Drag", proc=StartSplineDrag
  417.     KillControl PauseResumeSplineDrag
  418.     GraphNormal
  419.     RemoveAndKillNodeSplineWaves()
  420. End
  421.